/*
 * Rational.cpp
 *
 *  Created on: Dec 16, 2011
 *      Author: anna
 */

#include "Rational.h"
#include <cstdlib>
#include <iostream>

Rational::Rational(int nominator) {
	this->nominator = nominator;
	this->denominator = 1;
}

Rational::Rational(int nominator, int denominator) {
	if (denominator < 0) {
		denominator *= -1;
		nominator *= -1;
	}
	this->nominator = nominator;
	this->denominator = denominator;
	this->normalize();
}

Rational::Rational(const Rational& r) {
	this->nominator = r.nominator;
	this->denominator = r.denominator;
}

Rational& Rational::operator =(const Rational& r) {
	Rational tmp = Rational(r);
	std::swap(tmp.nominator, this->nominator);
	std::swap(tmp.denominator, this->nominator);
	return *this;
}

Rational& Rational::operator *=(const Rational& r) {
	this->nominator *= r.nominator;
	this->denominator *= r.denominator;
	this->normalize();
	return *this;
}

Rational& Rational::operator /=(const Rational& r) {
	this->nominator *= r.denominator;
	this->denominator *= r.nominator;
	this->normalize();
	return *this;
}

Rational& Rational::operator -=(const Rational& r) {
	this->denominator = (this->denominator * r.denominator);
	this->nominator = this->nominator * r.denominator - r.nominator * this->denominator;
	this->normalize();
	return *this;
}

Rational& Rational::operator +=(const Rational& r) {
	this->denominator = (this->denominator * r.denominator);
	this->nominator = this->nominator * r.denominator + r.nominator * this->denominator;
	this->normalize();
	return *this;
}

Rational& Rational::operator ++() {
	this->nominator += this->denominator;
	return *this;
}

Rational Rational::operator ++(int) {
	Rational result = Rational(*this);
	this->nominator += this->denominator;
	return result;
}

Rational& Rational::operator --() {
	this->nominator -= this->denominator;
	return *this;
}

Rational Rational::operator --(int) {
	Rational result = Rational(*this);
	this->nominator -= this->denominator;
	return result;
}

Rational::operator double() {
	return ((double) this->nominator) / this->denominator;
}

int Rational::get_nominator() const {
	return this->nominator;
}

int Rational::get_denominator() const {
	return this->denominator;
}

void Rational::normalize() {
	int n = nod(this->nominator, this->denominator);
	this->nominator /= n;
	this->denominator /= n;
}

Rational operator+ (const Rational& a, const Rational& b) {
	return Rational(a.get_nominator() * b.get_denominator() + a.get_denominator() * b.get_nominator(),
			a.get_denominator() * b.get_denominator());
}

Rational operator- (const Rational& a, const Rational& b) {
	return Rational(a.get_nominator() * b.get_denominator() - a.get_denominator() * b.get_nominator(),
				a.get_denominator() * b.get_denominator());
}

Rational operator* (const Rational& a, const Rational& b) {
	return Rational(a.get_nominator() * b.get_nominator(), a.get_denominator() * b.get_denominator());
}

Rational operator/ (const Rational& a, const Rational& b) {
	return Rational(a.get_nominator() * b.get_denominator(), a.get_denominator() * b.get_nominator());
}

bool operator== (const Rational& a, const Rational& b) {
	return (a.get_nominator() == b.get_nominator()) && (a.get_denominator() == b.get_denominator());
}

bool operator!= (const Rational& a, const Rational& b) {
	return !(a == b);
}

bool operator<= (const Rational& a, const Rational& b) {
	return (a - b).get_nominator() <= 0;
}

bool operator>= (const Rational& a, const Rational& b) {
	return (a - b).get_nominator() >= 0;
}

bool operator<  (const Rational& a, const Rational& b) {
	return (a - b).get_nominator() < 0;
}

bool operator>  (const Rational& a, const Rational& b) {
	return (a - b).get_nominator() > 0;
}



int nod(int a, int b) {
	a = abs(a);
	b = abs(b);
	while (a != b) {
		if (a == 0) {
			return b;
		}
		if (b == 0) {
			return a;
		}
		if (a > b) {
			a = a % b;
		} else {
			b = b % a;
		}
	}
	return a;
}

